package com.chen.gulimall.gulimallproduct.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.chen.gulimall.gulimallproduct.entity.*;
import com.chen.gulimall.gulimallproduct.feign.CouponFeign;
import com.chen.gulimall.gulimallproduct.feign.SearchFeignService;
import com.chen.gulimall.gulimallproduct.feign.WareFeignService;
import com.chen.gulimall.gulimallproduct.service.*;
import com.chen.gulimall.gulimallproduct.to.BoundTo;
import com.chen.gulimall.gulimallproduct.vo.*;
import com.chen.gulimallcommon.common.constant.ProductConstant;
import com.chen.gulimallcommon.common.to.FullReduceTo;
import com.chen.gulimallcommon.common.to.HasStockTo;
import com.chen.gulimallcommon.common.to.es.SkuEsModel;
import com.chen.gulimallcommon.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.chen.gulimallcommon.common.utils.PageUtils;
import com.chen.gulimallcommon.common.utils.Query;

import com.chen.gulimall.gulimallproduct.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {

    @Autowired
    SpuInfoDescService spuInfoDescService;

    @Autowired
    SpuImagesService spuImagesService;

    @Autowired
    AttrService attrService;

    @Autowired
    ProductAttrValueService productAttrValueService;

    @Autowired
    SkuInfoService skuInfoService;

    @Autowired
    SkuImagesService skuImagesService;

    @Autowired
    SkuSaleAttrValueService skuSaleAttrValueService;

    @Autowired
    CouponFeign couponFeign;

    @Autowired
    BrandService brandService;

    @Autowired
    CategoryService categoryService;

    @Autowired
    WareFeignService wareFeignService;


    @Autowired
    SearchFeignService searchFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }

    //插入商品需有一个事件
    @Transactional
    @Override
    public void saveSpuInfo(SpuSaveVo spuInfo) {

        //插入spu基本数据
        SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
        BeanUtils.copyProperties(spuInfo,spuInfoEntity);
        spuInfoEntity.setCreateTime(new Date());
        spuInfoEntity.setUpdateTime(new Date());

        this.baseMapper.insert(spuInfoEntity);

        //插入spu详细描述信息

        List<String> desc = spuInfo.getDecript();
       SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();
       spuInfoDescEntity.setSpuId(spuInfoEntity.getId());
       spuInfoDescEntity.setDecript(String.join(",",desc));
        spuInfoDescService.save(spuInfoDescEntity);

        //插入spu图片信息
        List<String> images = spuInfo.getImages();
        spuImagesService.saveImages(spuInfoEntity.getId(),images);

        //插入spu关联的attr的值
        List<BaseAttrs> attrs = spuInfo.getBaseAttrs();
        List<ProductAttrValueEntity> data = attrs.stream().map(item-> {
            ProductAttrValueEntity attrEntity = new ProductAttrValueEntity();
            AttrEntity entity = attrService.getById(item.getAttrId());
            attrEntity.setAttrName(entity.getAttrName());
            attrEntity.setAttrId(item.getAttrId());
            attrEntity.setAttrValue(item.getAttrValues());
            attrEntity.setQuickShow(item.getShowDesc());
            attrEntity.setSpuId(spuInfoEntity.getId());
            return attrEntity;
        }).collect(Collectors.toList());

        productAttrValueService.saveBatch(data);

        //保存spu对应的sku信息
        List<Skus> skuses = spuInfo.getSkus();

        if (skuses == null || skuses.size() == 0) {

        }else {
            skuses.forEach(item-> {
                String defaultImage = "";
                for (Images image : item.getImages()) {
                    if (image.getDefaultImg() == 1) defaultImage = image.getImgUrl();
                }
                //保存sku的基本信息
                    SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
                    BeanUtils.copyProperties(item,skuInfoEntity);
                    skuInfoEntity.setBrandId(spuInfo.getBrandId());
                    skuInfoEntity.setCatalogId(spuInfo.getCatalogId());
                    skuInfoEntity.setSpuId(spuInfoEntity.getId());
                    skuInfoEntity.setSkuDefaultImg(defaultImage);
                    skuInfoEntity.setSaleCount(0L);
                    skuInfoService.save(skuInfoEntity);
                    Long skuId = skuInfoEntity.getSkuId();

                    //保存sku的对应的图片信息
                    List<SkuImagesEntity> skuImagesEntities = item.getImages().stream().map(img-> {
                        SkuImagesEntity imagesEntity = new SkuImagesEntity();
                        imagesEntity.setSkuId(skuId);
                        imagesEntity.setDefaultImg(img.getDefaultImg());
                        imagesEntity.setImgUrl(img.getImgUrl());
                        return imagesEntity;
                    }).filter(skuImagesEntity -> {
                        //过滤结果集，当返回true时则可以放入结果集中
                        return !StringUtils.isEmpty(skuImagesEntity.getImgUrl());

                    }).collect(Collectors.toList());
                    skuImagesService.saveBatch(skuImagesEntities);

                    //保存sku对应的attr信息
                    List<Attr> attrList = item.getAttr();
                    List<SkuSaleAttrValueEntity> entities = attrList.stream().map(attr -> {
                        SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();
                        BeanUtils.copyProperties(attr,skuSaleAttrValueEntity);
                        skuSaleAttrValueEntity.setSkuId(skuId);
                        return skuSaleAttrValueEntity;
                    }).collect(Collectors.toList());

                    skuSaleAttrValueService.saveBatch(entities);

                //保存满减信息，通过feign进行服务之间的远程调用
                FullReduceTo fullReduceTo = new FullReduceTo();
                BeanUtils.copyProperties(item,fullReduceTo);
                fullReduceTo.setSkuId(skuId);
                //进行判断，只有当满减或者打折任何一个不为0时才可以保存，不然数据库中没有意义
                if (fullReduceTo.getFullCount() > 0 || fullReduceTo.getFullPrice().compareTo(new BigDecimal("0")) == 1) {
                    R r =  couponFeign.saveFullReduce(fullReduceTo);
                    if (r.getCode() != 0) {
                        log.error("远程调用服务保存满减信息失败！");
                    }

                }
            });
        }

        BoundTo boundVo = new BoundTo();
        Bounds bounds = spuInfo.getBounds();
        BeanUtils.copyProperties(bounds,boundVo);
        boundVo.setSpuId(spuInfoEntity.getId());
        R r = couponFeign.saveBounds(boundVo);

        if (r.getCode() != 0) {
            log.error("远程调用服务保存优惠信息失败！");
        }






    }

    //进行商品的关键字检索功能（spu商品信息）
    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {

        QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<SpuInfoEntity>();

        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)) {
            wrapper.and(item-> {
                item.eq("id",key).or().like("spu_name",key);
            });
        }

        String status = (String) params.get("status");
        if (!StringUtils.isEmpty(status)) {
            wrapper.eq("public_status",status);
        }

        String brandId = (String) params.get("brandId");
        if (!StringUtils.isEmpty(brandId) && !"0".equalsIgnoreCase(brandId)) {
            wrapper.eq("brand_id",brandId);
        }

        String catelogId = (String) params.get("catelogId");
        if (!StringUtils.isEmpty(key) && !"0".equalsIgnoreCase(catelogId)) {
            wrapper.eq("catelog_id",catelogId);
        }

        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                wrapper
        );

        return new PageUtils(page);
    }



    @Override
    public void up(Long spuId) {
        List<SkuInfoEntity> list = skuInfoService.list(new QueryWrapper<SkuInfoEntity>().eq("spu_id",spuId));

        List<Long> skuIds = list.stream().map(skuInfoEntity-> {
            return skuInfoEntity.getSkuId();
        }).collect(Collectors.toList());

        //发送远程调用请求，来判断是否有库存
        //要进行异常处理
        Map<Long, Boolean> hasStockMap = null;
        try {
            R r = wareFeignService.hasStock(skuIds);
            TypeReference<List<HasStockTo>> typeReference = new TypeReference<List<HasStockTo>>(){};
            hasStockMap = ((List<HasStockTo>) r.getData(typeReference)).stream().collect(Collectors.toMap(HasStockTo::getSkuId,item -> item.isHasStock()));

        }catch (Exception e) {
            log.error("判断sku仓库是否有值的远程调用失败，商品上架失败！");
        }

        //查询sku的检索属性
        List<ProductAttrValueEntity> attrList = productAttrValueService.list(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id",spuId));
        List<Long> attrIds = attrList.stream().map(attr -> {
            return attr.getAttrId();
        }).collect(Collectors.toList());
        //查询type为1的规格参数的attrId
        System.out.println(attrIds.toString());
        List<Long> attrId = attrService.selectAttrByIds(attrIds);
        Set<Long> set = new HashSet<>(attrId);
        List<SkuEsModel.Attrs> collect1 = attrList.stream().filter(attr -> {
            //过滤不是规格参数的attr
            return set.contains(attr.getAttrId());
        }).map(item-> {
            //为attrs中的值赋值（为skuEsModel中的attrs赋值）
            SkuEsModel.Attrs attrs = new SkuEsModel.Attrs();
            BeanUtils.copyProperties(item,attrs);
            return attrs;
        }).collect(Collectors.toList());


        Map<Long, Boolean> finalHasStockMap = hasStockMap;
        List<SkuEsModel> collect = list.stream().map(sku -> {
            //此对象中的属性为前台全文检索所需要渲染到前面的属性
            SkuEsModel skuEsModel = new SkuEsModel();
            BeanUtils.copyProperties(sku, skuEsModel);
            skuEsModel.setSkuPrice(sku.getPrice());
            //sku默认图片
            skuEsModel.setSkuImg(sku.getSkuDefaultImg());
            BrandEntity brandEntity = brandService.getById(sku.getBrandId());
            skuEsModel.setBrandName(brandEntity.getName());
            //品牌logo
            skuEsModel.setBrandImg(brandEntity.getLogo());
            //所属分类名称
            skuEsModel.setCatalogName(categoryService.getById(sku.getCatalogId()).getName());
            //设置它的热度
            skuEsModel.setHotScore(0L);
            //设置它的规格参数的值
            skuEsModel.setAttrs(collect1);
            //设置它是否有库存(当远程调用失败时map为null)
            if (finalHasStockMap == null) {
                skuEsModel.setHasStock(true);
            }else {
                skuEsModel.setHasStock(finalHasStockMap.get(sku.getSkuId()));
            }

            return skuEsModel;
        }).collect(Collectors.toList());
        R r = searchFeignService.productStatusUp(collect);

        if (r.getCode() == 0) {
            //保存数据到elasticsearch中成功
            //修改该spu中的属性为已上架
            baseMapper.updateStatus(spuId, ProductConstant.StatusEnum.SPU_UP.getCode());
        }else {

        }



    }

    @Override
    public SpuInfoEntity getSpuInfoBySkuId(Long skuId) {
        //先查询sku表里的数据
        SkuInfoEntity skuInfoEntity = skuInfoService.getById(skuId);

        //获得spuId
        Long spuId = skuInfoEntity.getSpuId();

        //再通过spuId查询spuInfo信息表里的数据
        SpuInfoEntity spuInfoEntity = this.baseMapper.selectById(spuId);

        //查询品牌表的数据获取品牌名
        BrandEntity brandEntity = brandService.getById(spuInfoEntity.getBrandId());
        spuInfoEntity.setBrandName(brandEntity.getName());

        return spuInfoEntity;

    }

}